﻿Imports System.Drawing.Drawing2D

Public Class MenuPage : Inherits Page

	ReadOnly Property Leaf As Boolean
		Get
			Return Not (From i In Menu.Items Where i.HasItems).Any
		End Get
	End Property

	Overrides Property Menu As MenuItem
		Get
			Return MyBase.Menu
		End Get
		Set(value As MenuItem)
			MyBase.Menu = value
			Text = Menu.Text
			If Not Leaf Then
				For Each Item In Menu.Items
					If Not Item.Image Is Nothing AndAlso Item.Text <> "-" AndAlso Not Item.Text.StartsWith("""") Then
						Dim L As New Label
						L.Text = Item.Text
						Labels.Add(L)
						L.Item = Item
						L.Type = "1"
						For Each SubItem In Item.Items
							If Not SubItem.Image Is Nothing AndAlso SubItem.Text <> "-" AndAlso Not SubItem.Text.StartsWith("""") Then
								Dim L1 As New Label
								L1.Text = SubItem.Text
								Labels.Add(L1)
								L1.Item = SubItem
								L1.Type = "2"
							End If
						Next
					End If
				Next
			Else
				For Each SubItem In Menu.Items
					If Not SubItem.Image Is Nothing Then
						If SubItem.Text = "-" Then
							Dim L1 As New Label
							L1.Text = ""
							Labels.Add(L1)
							L1.Type = "2"
						ElseIf SubItem.Text.StartsWith("""") Then
							Dim L1 As New Label
							L1.Text = SubItem.Text.Replace("""", "")
							Labels.Add(L1)
							L1.Type = "2"
						Else
							Dim L1 As New Label
							L1.Text = SubItem.Text
							Labels.Add(L1)
							L1.Item = SubItem
							L1.Type = "2"
						End If
					End If
				Next
			End If
			For Each Label In Labels
				Select Case Label.Type
					Case "1"
						Label.Font = New Font(Font.Name, Font.Size + 0)
						Label.ForeColor = Color.Green
					Case "2"
						Label.Font = New Font(Font.Name, Font.Size + 0)
						Label.ForeColor = Color.DarkSlateGray
				End Select
			Next
			Rearrange()
			If Labels.Count > 0 Then Focused = Labels.First
		End Set
	End Property

	Dim WithEvents Title As New PictureBox
	Dim WithEvents Contents As New UserControl
	Dim WithEvents Button As New Button
	Shadows Padding As Padding

	Sub New(Menu As MenuItem)
		MyBase.New()
		Controls.Clear()
		Controls.Add(Title)
		Title.Dock = DockStyle.Top
		Title.Height = 44
		Controls.Add(Contents)
		Contents.Dock = DockStyle.Fill
		Contents.BringToFront()
		Padding = New Padding(24)
		Me.Menu = Menu
		Title.Controls.Add(Button)
		Button.Text = "Klasik görünüm"
		Button.Size = New Size(112, Title.Height - 16)
		Button.TabStop = False
		Button.Location = New Point(Width - Button.Width - 8, 8)
		Button.Anchor = AnchorStyles.Right + Top
	End Sub

	Dim Labels As New List(Of Label)

	Private Sub Title_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Title.Paint
		e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
		e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear
		Dim R = New Rectangle(0, 0, Width, Title.Height)
		e.Graphics.FillRectangle(Themes.Current.FormColor.Opacity(128).Brush, R)
		e.Graphics.DrawLine(Color.Black.Opacity(64).Pen, R.Left, R.Bottom - 1, R.Right, R.Bottom - 1)
		Dim RI = R
		RI.Width = R.Height
		R.Offset(RI.Width, 0)
		RI.Inflate(-8, -8)
		e.Graphics.DrawImage(Menu.Image, RI)
		R.Height -= 3
		'DrawText2(e.Graphics, Menu.Text, New Font(Font.Name, Font.Size + 4), Color.Black, R, StrFormat("lm"))
		DrawStringLighted(e.Graphics, Menu.Text, New Font(Font.Name, Font.Size + 3), Color.Black, R, StrFormat("lm"), 2, 0)
	End Sub

	Private Sub Contents_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Contents.Paint
		e.Graphics.Clear(Color.White)
		e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
		e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear
		e.Graphics.TranslateTransform(-Contents.HorizontalScroll.Value, -Contents.VerticalScroll.Value)
		For Each Label In Labels
			Label.Draw(e, Label Is Selected, Label Is Focused)
		Next
	End Sub

	Dim _Selected As Label
	Shadows Property Selected As Label
		Get
			Return _Selected
		End Get
		Set(value As Label)
			If value Is Selected Then Return
			If Not Selected Is Nothing Then Invalidate(Selected.Rect)
			_Selected = value
			If Not Selected Is Nothing Then Invalidate(Selected.Rect)
		End Set
	End Property

	Dim _Focused As Label
	Shadows Property Focused As Label
		Get
			Return _Focused
		End Get
		Set(value As Label)
			If value Is Focused Then Return
			If Not Focused Is Nothing Then Invalidate(Focused.Rect)
			_Focused = value
			If Not Focused Is Nothing Then Invalidate(Focused.Rect)
			Dim R = Focused.Rect
			R.Offset(0, -Contents.VerticalScroll.Value)
			If R.Top - Padding.Top < 0 Then
				Contents.AutoScrollPosition = New Point(0, Focused.Rect.Top - Padding.Top)
			ElseIf R.Bottom + Padding.Bottom > Contents.Height Then
				Contents.AutoScrollPosition = New Point(0, Focused.Rect.Bottom - Contents.Height + Padding.Bottom)
			End If
		End Set
	End Property

	Shadows Sub Invalidate(R As Rectangle)
		R.Offset(-Contents.HorizontalScroll.Value, -Contents.VerticalScroll.Value)
		Contents.Invalidate(R)
	End Sub

	Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, keyData As System.Windows.Forms.Keys) As Boolean
		Select Case keyData
			Case Keys.Down
				Dim t = (From l In Labels Where Labels.IndexOf(l) > Labels.IndexOf(Focused))
				If t.Any Then Focused = t.First
				Return True
			Case Keys.Up
				Dim t = (From l In Labels Where Labels.IndexOf(l) < Labels.IndexOf(Focused))
				If t.Any Then Focused = t.Last
				Return True
			Case Keys.Right
				Dim t = (From l In Labels Where l.Location.X > Focused.Location.X Let d = Math.Abs(l.Location.Y - Focused.Location.Y) Order By l.Location.X, d Select l)
				If t.Any Then Focused = t.First
				Return True
			Case Keys.Left
				Dim t = (From l In Labels Where l.Location.X < Focused.Location.X Let d = Math.Abs(l.Location.Y - Focused.Location.Y) Order By l.Location.X Descending, d Select l)
				If t.Any Then Focused = t.First
				Return True
			Case Keys.Enter
				If Not Focused Is Nothing Then Focused.Item.Launch(Window)
				Return True
			Case Keys.Back
				Window.GoBack()
				Return True
			Case Keys.Escape
				Window.GoBack()
				Return True
		End Select
		Return MyBase.ProcessCmdKey(msg, keyData)
	End Function


	Private Sub Contents_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Contents.MouseMove
		Dim p = e.Location
		p.Offset(Contents.HorizontalScroll.Value, Contents.VerticalScroll.Value)
		For Each Label In (From l In Labels Where Not l.ReadOnly)
			If Label.Rect.Contains(p) Then
				Selected = Label
				Cursor = Cursors.Hand
				Return
			End If
		Next
		Selected = Nothing
		Cursor = Cursors.Default
	End Sub

	Private Sub Contents_MouseLeave(sender As Object, e As System.EventArgs) Handles Contents.MouseLeave
		Selected = Nothing
	End Sub

	Private Sub Contents_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Contents.MouseDown
		If Selected Is Nothing Then Return
		Focused = Selected
		Selected.Item.Launch(Window)
	End Sub

	Sub Rearrange()
		Dim y = Padding.Top
		Dim x = Padding.Left
		If Labels.Count = 0 Then Return
		Dim MaxWidth = (From l In Labels Select l.Width).Max
		Dim PrevType As String = ""
		For Each Label In Labels
			If Label.Type = "1" Then
				If PrevType = "2" Then y += Label.Height * 1.5
				If y + Label.Height * 3 + Padding.Bottom > Contents.Height Then
					x += MaxWidth + Padding.Left
					y = Padding.Top
				End If
				Label.Location = New Point(x, y)
				y += Label.Height * 1.5
			ElseIf Label.Type = "2" Then
				'Label.Width = MaxWidth
				If y + Label.Height + Padding.Bottom > Contents.Height Then
					x += MaxWidth + Padding.Left
					y = Padding.Top
				End If
				Label.Location = New Point(x, y)
				y += Label.Height * 1.5
			End If
			PrevType = Label.Type
		Next
		'y += Labels.Last.Height * 1.6
		Contents.AutoScrollMinSize = New Size(x + MaxWidth + Padding.Horizontal, 0)
		Contents.Invalidate()
	End Sub

	Protected Overrides Sub OnSizeChanged(e As System.EventArgs)
		MyBase.OnSizeChanged(e)
		Rearrange()
	End Sub

	Class Label

		Dim _Font As Font
		Private _contains As Boolean

		Property Font As Drawing.Font
			Get
				Return _Font
			End Get
			Set(value As Drawing.Font)
				_Font = value
				Measure()
			End Set
		End Property

		Dim _Text As String
		Property Text As String
			Get
				Return _Text
			End Get
			Set(value As String)
				_Text = value
				Measure()
			End Set
		End Property

		Property Height As Double

		Property Item As SSD.MenuItem

		ReadOnly Property Rect As Rectangle
			Get
				Dim R = New Rectangle(Location, New Size(Width, Height))
				R.Inflate(4, 4)
				Return R
			End Get
		End Property

		Property Type As String

		Property [ReadOnly] As Boolean

		Property Underline As Boolean


		Sub Measure()
			Dim s = MeasureText(Text, Font)
			Height = s.Height
			Width = s.Width + Height
		End Sub

		Property Location As Point

		Property ForeColor As Color

		Property Width As Integer

		Sub Draw(e As PaintEventArgs, Selected As Boolean, Focused As Boolean)
			e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear
			e.Graphics.SmoothingMode = SmoothingMode.HighQuality
			e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality
			If Focused Then e.Graphics.FillRoundRect(Rect, Themes.Current.FormColor.Mix(Color.White, 50).Brush, 4)
			Renderer.PaintButton(e.Graphics, Rect, Nothing, False, Selected, False, True, Not Focused)
			Dim RI = Rect
			RI.Width = RI.Height
			RI.Inflate(-2, -2)
			If Not Item.Image Is Nothing Then
				RI.Inflate(-RI.Width / 16, -RI.Width / 16)
				e.Graphics.DrawImage(Item.Image, RI)
			End If
			Dim R = Rect
			R.Height -= 1
			If Underline Then
				e.Graphics.DrawLine(ForeColor.Pen, R.Left, R.Bottom, R.Right, R.Bottom)
			End If
			R.Offset(RI.Width + 8, 0)
			DrawText2(e.Graphics, Text, Font, ForeColor, R, StrFormat("lm"))
		End Sub

	End Class

	Private Sub Button_Click(sender As Object, e As System.EventArgs) Handles Button.Click
		Window.ClassicView()
	End Sub

End Class
